package ensemble.util

import java.nio.file.{Files => JFiles, Path, Paths}
import collection.JavaConverters._
import java.io._
import ensemble.pages.{SamplePage, CategoryPage}
import com.google.common.io.Files
import scala.Some
import ensemble.pages.CategoryPage
import com.google.common.base.Strings

object PageListGenerator {

  object AScalaFile {
    def unapply(f: Path) = if (JFiles.isRegularFile(f) && f.toString.endsWith(".scala")) Some(f) else None
  }

  object ADir {
    def unapply(f: Path) = if (JFiles.isDirectory(f)) Some(f) else None
  }


  val sampleRootPath = Paths.get(getClass.getResource("/ensemble/samples").toURI)
  val rootPath = Paths.get(getClass.getResource("/").toURI)

  def getSamplePage(f: Path): SamplePage = {
    val onlyName = Files.getNameWithoutExtension(f.getFileName.toString)
    val name = camelSplit(onlyName).toList.dropRight(2).mkString(" ")
    val qualifiedClass = rootPath.relativize(f).toString.replaceAll("/", ".").dropRight(".scala".length)
    SamplePage(name, qualifiedClass)
  }

  def camelSplit(str: String) = """([A-Z][A-Z0-9]*(?=$|[A-Z][a-z0-9])|[A-Za-z][a-z0-9]+)""".r findAllIn str

  def getCategoryPage(dir: Path): CategoryPage = {
    val children = JFiles.newDirectoryStream(dir).asScala.collect {
      case AScalaFile(f) =>
        println("scala file found:" + f)
        getSamplePage(f)
      case ADir(d) => getCategoryPage(d)
    }
    val name = dir.getFileName.toString.capitalize
    CategoryPage(name.toString, children.toSeq: _*)
  }

  val destFilePath = sampleRootPath.resolve("page_list.json")

  import org.json4s._
  import org.json4s.native.Serialization

  implicit val formats = Serialization.formats(
    FullTypeHints(classOf[CategoryPage] :: classOf[SamplePage] :: Nil)
  )

  def main(args: Array[String]) {
    val writer = new BufferedWriter(new FileWriter(destFilePath.toFile))
    val toWrite = getCategoryPage(sampleRootPath)
    writer.write(Serialization.write(toWrite))
    writer.close()
  }

  def readSamples = {
    val reader = new BufferedReader(new FileReader(destFilePath.toFile))
    val readBack = Serialization.read[CategoryPage](reader)
    reader.close()
    readBack
  }

}
